﻿Imports System.Math
Public Class SpiPoint
    Inherits Points
    Public ZH, HY, QZ, YH, HZ As New Points
    Public m, p, beta As Double
    Public TH, LH, EH, q As Double
    Public startPoint, JD, endPoint As New Points
    Public alpha, alpha1, alpha2 As Double
    '是否是右转折角的标志，默认是右转折角
    Public flag As Boolean = True

    Public Sub cal(startP As Points, JDP As Points, endP As Points)
        startPoint = startP
        JD = JDP
        endPoint = endP
        Dim a1, a2 As Double
        a1 = getAzimuth(startPoint, JD)
        a2 = getAzimuth(JD, endPoint)
        alpha = a2 - a1
        If alpha < 0 Then
            alpha = Abs(alpha)
            flag = False
        End If
        alpha1 = a1
        alpha2 = getAzimuth(endPoint, JD)

        ZH.name = "ZH" : HY.name = "HY" : QZ.name = "QZ"
        YH.name = "YH" : HZ.name = "HZ" : JD.name = "JD"
        ZH.isZD = True : HY.isZD = True : QZ.isZD = True
        YH.isZD = True : HZ.isZD = True : JD.isZD = False
        ZH.pType = "HQX" : HY.pType = "HQX" : QZ.pType = "HQX"
        YH.pType = "HQX" : HZ.pType = "HQX" : JD.pType = "JD"
        Dim t As Double = getKil(startPoint, JD)
        JD.k = getKil(startPoint, JD) + startPoint.k

        getSpiFactor()
        getZDKil()
        getZDCoor()
    End Sub

    Public Sub getSpiFactor()
        '计算缓和曲线参数
        m = JD.LS / 2 - Pow(JD.LS, 3) / (240 * Pow(JD.R, 2))
        p = Pow(JD.LS, 2) / (24 * JD.R)
        beta = JD.LS / (2 * JD.R)
        '计算曲线综合要素
        TH = m + (JD.R + p) * Tan(alpha / 2)
        LH = JD.R * (alpha - 2 * beta) + 2 * JD.LS
        EH = (JD.R + p) * (1 / Cos(alpha / 2)) - JD.R
        q = 2 * TH - LH
    End Sub
    Public Sub getZDKil()
        ZH.k = JD.k - TH
        HY.k = ZH.k + JD.LS
        QZ.k = ZH.k + LH / 2
        YH.k = ZH.k + LH - JD.LS
        HZ.k = YH.k + JD.LS
    End Sub
    Public Sub getZDCoor()
        ZH.x = JD.x - TH * Cos(alpha1)
        ZH.y = JD.y - TH * Sin(alpha1)
        HZ.x = JD.x - TH * Cos(alpha2)
        HZ.y = JD.y - TH * Sin(alpha2)

        QZ.x = getCoor(QZ.k, QZ).x
        QZ.y = getCoor(QZ.k, QZ).y

        HY.x = getCoor(HY.k, HY).x
        HY.y = getCoor(HY.k, HY).y

        YH.x = getCoor(YH.k, YH).x
        YH.y = getCoor(YH.k, YH).y
    End Sub

    Public Function getCoor(k As Double, point As Points)
        Dim x1, y1 As Double
        Dim L As Double
        If k <= QZ.k Then
            L = k - ZH.k
            If k <= HY.k Then
                x1 = L - Pow(L, 5) / (40 * Pow(JD.R, 2) * Pow(JD.LS, 2))
                y1 = Pow(L, 3) / (6 * JD.R * JD.LS)
            Else
                Dim phi As Double
                phi = (L - 0.5 * JD.LS) / JD.R
                x1 = m + JD.R * Sin(phi)
                y1 = p + JD.R * (1 - Cos(phi))
            End If
        Else
            L = HZ.k - k
            If k >= YH.k Then
                x1 = L - Pow(L, 5) / (40 * Pow(JD.R, 2) * Pow(JD.LS, 2))
                y1 = Pow(L, 3) / (6 * JD.R * JD.LS)
            Else
                Dim phi As Double
                phi = (L - 0.5 * JD.LS) / JD.R
                x1 = m + JD.R * Sin(phi)
                y1 = p + JD.R * (1 - Cos(phi))
            End If
        End If
        If flag Then
            If k <= QZ.k Then
                point.x = ZH.x + x1 * Cos(alpha1) - y1 * Sin(alpha1)
                point.y = ZH.y + x1 * Sin(alpha1) + y1 * Cos(alpha1)
            Else
                point.x = HZ.x + x1 * Cos(alpha2) + y1 * Sin(alpha2)
                point.y = HZ.y + x1 * Sin(alpha2) - y1 * Cos(alpha2)
            End If
        Else
            If k <= QZ.k Then
                point.x = ZH.x + x1 * Cos(alpha1) + y1 * Sin(alpha1)
                point.y = ZH.y + x1 * Sin(alpha1) - y1 * Cos(alpha1)
            Else
                point.x = HZ.x + x1 * Cos(alpha2) - y1 * Sin(alpha2)
                point.y = HZ.y + x1 * Sin(alpha2) + y1 * Cos(alpha2)
            End If
        End If

        Return point
    End Function
End Class
